# 正确的滑动窗口解法


class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:

        if not s:
            return 0

        char_index = {}  # 字符 -> 最后出现的索引
        max_length = 0
        left = 0  # 窗口左边界

        for right, char in enumerate(s):

            # 如果字符重复了，且重复位置在当前窗口内
            if char in char_index and char_index[char] >= left:
                # 移动左边界到重复字符的下一个位置
                left = char_index[char] + 1
            # 更新字符的位置
            char_index[char] = right
            # 计算当前窗口长度
            current_length = right - left + 1
            current_window = s[left : right + 1]
            if current_length > max_length:
                max_length = current_length
            else:
                print(f"    当前子串: '{current_window}' (长度{current_length})")

        return max_length


# 测试
if __name__ == "__main__":
    solution = Solution()

    test_cases = [
        ("dvcvf", 3),
        ("abcabcbb", 3),
        ("bbbbb", 1),
        ("pwwkew", 3),
        ("", 0),
        ("au", 2),
    ]

    for s, expected in test_cases:
        result = solution.lengthOfLongestSubstring(s)
        status = "✓" if result == expected else "✗"
        print(f'{status} 输入: "{s}" → 结果: {result}, 期望: {expected}\n')
        print("=" * 60 + "\n")
